# coding: utf-8
import warnings
import os
import yaml 

class DefaultConfig(object):
    """
    一个加载配置文件的类
    支持YAML(utf8)和命令行两种
    命令行会覆盖YAML中设定的命令, for example:
    --config="config.txt" --GPU_ID=0, 那么GPU_ID＝0就会覆盖config.txt里面的GPU_ID
    """

    config_dict = {
        # seed : 0,
        "USE_CUDA" : True,
        "GPU_ID" : (0,),

        "pre_checkpoint" : None,
        "resume" : None,
        "dataset_root" : "E:\\zhigan\\detection\\data",
        "dataset_file" : "E:\\zhigan\\detection\\labels.txt",
        "model_config_path":"./config/yolov3.cfg",
        "image_dim" : 256,

        "display" : 1,
        "save_interval" : 20000,
        "save_dir" : "./checkpoints",
        "save_prefix" : "yolov3",

        "net" : "yolov3",     # enet segnet
        "num_classes" : 1,
        "train_batch" : 2,
        "base_lr" : 0.01,
        "clip_grad" : 120.0,
        "momentum" : 0.9,
        "gamma" : 0.1,
        "weight_decay" : 0.0005,
        "stepsize" : [80, 200, 250],
        "max_epoch" : 300,
    }
    def _parse(self, kwargs):
        # 首先解析YAML
        cfg = None
        for k, v in kwargs.items():
            if k == "config":
                cfg = v

        if cfg is not None:
            # YAML loads
            with open(cfg, encoding='utf8') as f:
                cfg = f.read()
            cfg = yaml.load(cfg)
            for k in cfg:
                if k in self.config_dict.keys():
                    self.config_dict[k] = cfg[k]
                else:
                    warnings.warn("key: {} in config file, but inner class not implement it".format(k))

        # parse other command line
        for k, v in kwargs.items():
            if k not in self.config_dict.keys():
                warnings.warn("Warning: opt has not key: {}".format(k))
            if k != "config":
                self.config_dict[k] = v

        if isinstance(self.config_dict["GPU_ID"], int):
            self.config_dict["GPU_ID"] = (self.config_dict["GPU_ID"],)
        if isinstance(self.config_dict["stepsize"], int):
            warnings.warn("step size is a single int -> {}!".format(self.config_dict["stepsize"]))
        if not isinstance(self.config_dict["stepsize"], list):
            self.config_dict["stepsize"] = list(self.config_dict["stepsize"])

        # for None
        none_type = ["None", "none", "NONE"]
        for k in self.config_dict:
            if self.config_dict[k] in none_type:
                self.config_dict[k] = None

    def _state_dict(self):
        return self.config_dict

    def __getattr__(self, item):
        if item in self.config_dict:
            return self.config_dict[item]
        msg = "thers is no key of: {}".format(item)
        raise RuntimeError(msg)